package com.zhiyin.seal.controller;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhiyin.seal.entity.bo.*;
import com.zhiyin.seal.entity.dto.*;
import com.zhiyin.seal.entity.vo.*;
import com.zhiyin.seal.service.ApplyService;
import com.zhiyin.seal.service.FileService;
import com.zhiyin.seal.service.StampService;
import com.zhiyin.seal.service.UserService;
import com.zhiyin.seal.util.BeanUtil;
import com.zhiyin.seal.util.DateUtil;
import com.zhiyin.seal.util.ExcelUtil;
import com.zhiyin.seal.util.UUIDUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.zhiyin.seal.constant.SystemConstants.STAMP_RECORD_PARAM;

/**
 * 用印业务控制器
 */
@RestController
@RequestMapping("/stamp")
public class StampController {

    @Autowired
    StampService stampService;

    @Autowired
    ApplyService applyService;

    @Autowired
    UserService userService;

    @Autowired
    FileService fileService;

    @Value("${myconfig.domain}")
    private String domain;
    @Value("${myconfig.download-record-zip}")
    private String downloadRecordZip;

    @PostMapping("/start")
    public ResponseDTO<Long> startStamp(@RequestBody StartStampDTO startStampDTO){
        StartStampBo startStampBo = BeanUtil.copy(startStampDTO,StartStampBo.class);
        return ResponseDTO.succData(stampService.startStamp(startStampBo));
    }

    @PostMapping("/press")
    public ResponseDTO<Boolean> uploadStamp(@RequestBody StampPressDTO stampPressDTO) {
        StampPressBo stampPressBo = BeanUtil.copy(stampPressDTO,StampPressBo.class);
        return ResponseDTO.succData(stampService.uploadStamp(stampPressBo));
    }

    @PostMapping("/press/storage")
    public ResponseDTO<Boolean> uploadStampStorage(@RequestBody List<StampPressDTO> stampPressDTOList){
        List<StampPressBo> stampPressBoList = BeanUtil.copyList(stampPressDTOList,StampPressBo.class);
        return ResponseDTO.succData(stampService.uploadStampStorage(stampPressBoList));
    }

    @PostMapping("/record")
    public ResponseDTO<List<StampRecordVo>> getRecordList(@RequestBody StampSearchParamsDTO paramsDTO){
        if(paramsDTO.getCompanyId() == null){
            paramsDTO.setCompanyId(0l);
        }
        if(paramsDTO.getHasAdmin() == null){
            paramsDTO.setHasAdmin(false);
        }
        StampSearchParamsBo paramsBo = BeanUtil.copy(paramsDTO, StampSearchParamsBo.class);
        // 计算查询截止日期
        if(paramsDTO.getDuration() != null){
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.add(Calendar.DAY_OF_MONTH,-paramsDTO.getDuration());
            paramsBo.setCreateTime(DateUtil.COMMON_DATE_FORMATE.format(calendar.getTime()));
        }
        if(paramsBo.getPageNo() == null){
            paramsBo.setPageNo(0);
        }
        if(paramsBo.getPageSize() == null){
            paramsBo.setPageSize(20);
        }
        if(paramsBo.getPaging() == null){
            paramsBo.setPaging(true);
        }
        if(paramsDTO.getWhetherWeb() != null && paramsDTO.getWhetherWeb()){
            paramsBo.setPageNo(paramsBo.getPageNo() -1);
        }
        List<StampRecordBo> stampRecordBoList = stampService.getRecordList(paramsBo);
        List<StampRecordVo> stampRecordVoList = Lists.newArrayList();
        List<Long> applyIdList = stampRecordBoList.stream().map(StampRecordBo::getApplyId).collect(Collectors.toList());
        applyIdList = applyIdList.stream().distinct().collect(Collectors.toList());
        Map<Long,ApplyBo> applyBoMap = Maps.newHashMap();
        if(applyIdList.size() > 0){
            List<ApplyBo> applyBoList = applyService.getApplyListByIds(applyIdList);
            if(applyBoList != null){
                for (ApplyBo applyBo : applyBoList) {
                    applyBoMap.put(applyBo.getId(),applyBo);
                }
            }
        }
        for (StampRecordBo stampRecordBo : stampRecordBoList) {
            StampRecordVo stampRecordVo = BeanUtil.copy(stampRecordBo, StampRecordVo.class);
            stampRecordVo.setSealInfo(BeanUtil.copy(stampRecordBo.getSealInfo(),SealVo.class));
            stampRecordVo.setStampUser(BeanUtil.copy(stampRecordBo.getStampUser(), UserVo.class));
            stampRecordVo.setApplyInfo(BeanUtil.copy(applyBoMap.get(stampRecordBo.getApplyId()), ApplyVo.class));

            stampRecordVoList.add(stampRecordVo);
        }

        // 获取数据总数
        ResponseDTO responseDTO =  ResponseDTO.succData(stampRecordVoList);
        responseDTO.setTotalCount(stampService.getRecordTotalCount(paramsBo));

        return responseDTO;
    }

    @PostMapping("/record/export")
    public void exportRecordList(@RequestBody StampSearchParamsDTO paramsDTO, HttpServletResponse response) throws UnsupportedEncodingException {
        if(paramsDTO.getCompanyId() == null){
            paramsDTO.setCompanyId(0l);
        }
        if(paramsDTO.getHasAdmin() == null){
            paramsDTO.setHasAdmin(false);
        }
        StampSearchParamsBo paramsBo = BeanUtil.copy(paramsDTO, StampSearchParamsBo.class);
        // 计算查询截止日期
        if(paramsDTO.getDuration() != null){
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.add(Calendar.DAY_OF_MONTH,-paramsDTO.getDuration());
            paramsBo.setCreateTime(DateUtil.COMMON_DATE_FORMATE.format(calendar.getTime()));
        }
        paramsBo.setPaging(false);
        // 判断是否导出文件
        if(paramsDTO.getExportType() != null && paramsDTO.getExportType() > 0){
            response.setContentType("text/plain;charset=UTF-8");
            try {
                String requestId = UUIDUtil.getUUIDString();
                String url = domain + downloadRecordZip + "?requestId=" + requestId;
                STAMP_RECORD_PARAM.put(url,paramsBo);
                response.getWriter().write(url);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
        List<StampRecordBo> stampRecordBoList = stampService.getRecordList(paramsBo);
        if(stampRecordBoList.size() == 0){
            return;
        }
        // 加载关联单据
        List<ApplyBo> applyBoList = applyService.getStampRecordApplyList(paramsBo);
        Map<Long,String> userNickNameMap = Maps.newHashMap();
        if(applyBoList != null){
            List<Long> userIds = Lists.newArrayList();
            Map<Long,ApplyBo> applyBoMap = Maps.newHashMap();
            for (ApplyBo applyBo : applyBoList) {
                applyBoMap.put(applyBo.getId(),applyBo);
                userIds.add(applyBo.getCreateUser());
            }
            for (StampRecordBo stampRecordBo : stampRecordBoList) {
                stampRecordBo.setApplyInfo(applyBoMap.get(stampRecordBo.getApplyId()));
            }
            // 用户id列表去重复
            userIds = userIds.stream().distinct().collect(Collectors.toList());
            if(userIds.size() > 0){
                List<UserBo> userBoList = userService.getUserListByUserIdsAndCompany(userIds,paramsDTO.getCompanyId());
                userNickNameMap = userBoList.stream().collect(Collectors.toMap(UserBo::getId,UserBo::getNickName));
            }
        }
        //excel标题
        String[] title = {"用印事由","单据编号","文件名称","文件类型","申请人","申请时间","印章名称","用印人","盖章次数","用印时间","用印地址","所属公司"};
        //excel文件名
        String fileName = "stamp_record_"+System.currentTimeMillis()+".xls";
        //sheet名
        String sheetName = "盖章记录";
        String[][] content = new String[stampRecordBoList.size()][title.length];
        for (int i = 0; i < stampRecordBoList.size(); i++) {
            content[i] = new String[title.length];
            StampRecordBo stampRecordBo = stampRecordBoList.get(i);
            content[i][0] = stampRecordBo.getReason();
            ApplyBo applyBo = stampRecordBo.getApplyInfo();
            if(applyBo == null){
                content[i][1] = "";
                content[i][2] = "";
                content[i][3] = "";
                content[i][4] = "";
                content[i][5] = "";
            } else {
                content[i][1] = applyBo.getCode();
                content[i][2] = applyBo.getFileName();
                content[i][3] = applyBo.getFileType();
                content[i][4] = userNickNameMap.get(applyBo.getCreateUser());
                content[i][5] = DateUtil.COMMON_DATE_FORMATE.format(applyBo.getCreateTime());
            }
            SealBo sealBo = stampRecordBo.getSealInfo();
            if(sealBo == null){
                content[i][6] = "";
            } else {
                content[i][6] = sealBo.getName();
            }
            UserBo userBo = stampRecordBo.getStampUser();
            if(userBo == null){
                content[i][7] = "";
            } else {
                content[i][7] = userBo.getNickName();
            }
            content[i][8] = stampRecordBo.getStampCount().toString();
            content[i][9] = DateUtil.COMMON_DATE_FORMATE.format(stampRecordBo.getCreateTime());
            content[i][10] = stampRecordBo.getAddress();
            content[i][11] = stampRecordBo.getCompanyName();
        }
        //创建HSSFWorkbook
        HSSFWorkbook wb = ExcelUtil.getHSSFWorkbook(sheetName, title, content, null);
        //响应到客户端
        try {
            // 设置response的Header
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8"));
            OutputStream os = response.getOutputStream();
            wb.write(os);
            os.flush();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @GetMapping(value = "/record/zip")
    public void getRecordZip(@RequestParam String requestId,HttpServletResponse response) throws IOException{
        String url = domain + downloadRecordZip + "?requestId=" + requestId;
        StampSearchParamsBo paramsBo = STAMP_RECORD_PARAM.get(url);
        if(paramsBo != null) {
            List<ApplyBo> applyBoList = applyService.getStampRecordApplyList(paramsBo);
            fileService.exportFile(paramsBo.getExportType(),applyBoList,response);
            // 移除缓存
            STAMP_RECORD_PARAM.remove(url);
        } else {
            response.setContentType("text/plain;charset=UTF-8");
            try {
                response.getWriter().write("下载地址已失效！");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @GetMapping("/record/single")
    public ResponseDTO<StampRecordVo> getRecordById(@RequestParam Long stampRecordId){
        StampRecordBo stampRecordBo = stampService.getRecordById(stampRecordId);
        if(stampRecordBo == null){
            return ResponseDTO.succData(null);
        }
        StampRecordVo stampRecordVo = BeanUtil.copy(stampRecordBo, StampRecordVo.class);
        stampRecordVo.setSealInfo(BeanUtil.copy(stampRecordBo.getSealInfo(),SealVo.class));
        stampRecordVo.setStampUser(BeanUtil.copy(stampRecordBo.getStampUser(), UserVo.class));

        return ResponseDTO.succData(stampRecordVo);
    }

    @PostMapping("/upload/images")
    public ResponseDTO<Boolean> uploadStampImages(@RequestBody StampImageDTO stampImageDTO){
        if(stampImageDTO.getImageUrls().size() > 0){
            StampImageBo stampImageBo = new StampImageBo();
            stampImageBo.setApplyId(stampImageDTO.getApplyId());
            stampImageBo.setImageUrls(stampImageDTO.getImageUrls());

            stampService.uploadStampImages(stampImageBo);
        }
        
        return ResponseDTO.succData(true);
    }

    @GetMapping("/image/remove")
    public ResponseDTO<Boolean> removeStampImage(@RequestParam String imageUrl){
        return ResponseDTO.succData(stampService.removeStampImageList(imageUrl));
    }

    @GetMapping("/image/list")
    public ResponseDTO<List<String>> getStampImageList(@RequestParam Long applyId){
        return ResponseDTO.succData(stampService.getStampImageList(applyId));
    }

    @GetMapping("/record/detail")
    public ResponseDTO<List<StampRecordDetailVo>> getRecordDetailList(@RequestParam Long stampRecordId){
        List<StampRecordDetailVo> stampRecordDetailVoList = BeanUtil.copyList(stampService.getRecordDetailList(stampRecordId),StampRecordDetailVo.class);

        return ResponseDTO.succData(stampRecordDetailVoList);
    }

    @PostMapping("/fingerprint/upload")
    public ResponseDTO<Boolean> uploadFingerprintRecord(@RequestBody StampRecordFingerprintDTO stampRecordFingerprintDTO){
        StampRecordFingerprintBo stampRecordFingerprintBo = BeanUtil.copy(stampRecordFingerprintDTO,StampRecordFingerprintBo.class);
        stampRecordFingerprintBo.setStampTime(DateUtil.getDateFromString(stampRecordFingerprintDTO.getStampTime()));

        return ResponseDTO.succData(stampService.uploadFingerprintRecord(stampRecordFingerprintBo));
    }

    @GetMapping("/fingerprint/record")
    public ResponseDTO<List<StampRecordFingerprintVo>> getFingerprintRecordList(@RequestParam String mac,@RequestParam Integer code){
        List<StampRecordFingerprintBo> stampRecordFingerprintBoList = stampService.getFingerprintRecordList(mac,code);
        return ResponseDTO.succData(BeanUtil.copyList(stampRecordFingerprintBoList,StampRecordFingerprintVo.class));
    }
}